import os
import random
import time
import tornado.web
import tornado.ioloop
import tornado.websocket
import tornado.httpserver
from pycket.session import SessionMixin
import email_setting
from models import *
from settings import *


class BaseHandler(tornado.web.RequestHandler, SessionMixin):
    '''
    实现用户认证, 重写 get_current_user() 方法来判断当前用户,比如可以基于cookie的值
    '''

    def get_current_user(self):
        return self.session.get('user')


# 首页
class MainHandler(BaseHandler, SessionMixin):
    # 添加一个处理get请求方式的方法
    @tornado.web.authenticated
    def get(self):
        # 获取当前登录用户
        cur_user = self.session.get('user', None)
        if cur_user is not None:
            user = cur_user
        else:
            user = None
        # 获取商品列表
        shops = session.query(Goods).filter_by(status=1).all()
        # 获取商品所有图片
        for shop in shops:
            path = '{0}/static/{1}'.format(os.path.join(os.path.dirname(__file__)), shop.images)
            images = os.listdir(path)
            shop.photos = ["{0}/{1}".format(shop.images, i) for i in images]
            shop.photo = shop.photos[0]
        self.render('template/shop/index.html', title='首页', user=user, shops=shops)


# 详情
class DetailHandler(BaseHandler):
    def get(self, *args, **kwargs):
        good_id = self.get_argument('good', None)
        with session.no_autoflush:
            good = session.query(Goods).filter_by(id=int(good_id)).first()
        path = '{0}/static/{1}'.format(os.path.join(os.path.dirname(__file__)), good.images)
        images = os.listdir(path)
        good.photos = ['{0}/{1}'.format(good.images, i) for i in images]
        return self.render('template/shop/comody.html', title='{}详情'.format(good.name), good=good)


# 邮箱发送验证码
class SendCodeHandler(BaseHandler, SessionMixin):
    def post(self):
        try:
            email = self.get_argument('email')
            already_email = session.query(User).filter_by(email=email).first()
            if already_email is not None:
                return self.write({
                    'status': False,
                    'data': '该邮箱已被注册'
                })
            code = random.randint(100000, 999999)  # 获取随机验证码
            email_setting.email([email, ], str(code))  # 发送验证码到邮箱
            # 写入session(redis)
            self.session.set('code', code)
            return self.write({
                'status': True,
                'data': 'ok'
            })
        except Exception as e:
            return self.write({
                'status': False,
                'data': '发送失败'
            })


# 注册
class RegisterHandler(BaseHandler, SessionMixin):
    def get(self):
        return self.render('template/shop/register.html', title='用户注册')

    def post(self):
        try:
            username = self.get_argument('username')
            email = self.get_argument('email')
            password = self.get_argument('password')
            # 邮箱验证码
            email_code = self.get_argument('email_code')
            session_code = self.session.get('code')
            if str(email_code) != str(session_code):
                return self.write({
                    'status': False,
                    'data': '验证码错误'
                })
            # 判断用户名，邮箱是否已存在
            already_username = session.query(User).filter_by(username=username).first()
            already_email = session.query(User).filter_by(email=email).first()
            if already_username is not None:
                return self.write({
                    'status': False,
                    'data': '该用户名已存在'
                })
            elif already_email is not None:
                return self.write({
                    'status': False,
                    'data': '该邮箱已被注册'
                })
            user = User(username=username, password=password, email=email)
            session.add(user)
            session.commit()
            return self.write({
                'status': True,
                'data': 'ok'
            })
        except Exception as e:
            return self.write({
                'status': False,
                'data': 'Waring'
            })


# 登录
class LoginHandler(BaseHandler, SessionMixin):
    def get(self):
        self.render('template/shop/login.html', title='用户登录')

    def post(self):
        try:
            username = self.get_argument('username')
            password = self.get_argument('password')
            user = session.query(User).filter_by(username=username, password=password).first()
            if user is not None:
                # 保存登录状态
                self.session.set('user', user)
                data = {
                    'status': True,
                    'msg': 'ok'
                }
                self.write(data)
            else:
                data = {
                    'status': False,
                    'msg': 'fail'
                }
                self.write(data)
        except Exception as e:
            data = {
                'status': False,
                'msg': 'warring'
            }
            self.write(data)


# 进入聊天
class ChatHandler(BaseHandler, SessionMixin):
    @tornado.web.authenticated
    def get(self):
        try:
            my_id = self.session.get('user').id
            his_id = self.get_argument('his', '')
            if his_id.isdigit():
                self.set_cookie('his_id', his_id)
            else:
                return self.write('对方被外星人抓走了')
            # 获取双方用户信息
            with session.no_autoflush:
                me = session.query(User).filter_by(id=int(my_id)).first()
                he = session.query(User).filter_by(id=int(his_id)).first()
                # 获取聊天记录
                records = session.query(ChatRecord).filter(
                    or_(and_(ChatRecord.who_send == int(my_id), ChatRecord.who_recv == int(his_id)),
                        and_(ChatRecord.who_send == int(his_id), ChatRecord.who_recv == int(my_id)))).order_by(
                    'id').all()
            self.render('template/shop/chat.html', me=me, he=he, records=records)
        except Exception as e:
            print(e)
            self.write('呀，页面被外星人吃了！')


# WebSocket
class WebRTCServer(BaseHandler, SessionMixin):
    chats = dict()

    def open(self):
        my_id = self.session.get('user').id
        his_id = self.get_cookie('his_id')
        min_id = my_id
        max_id = his_id
        if int(min_id) > int(max_id):
            min_id, max_id = max_id, min_id
        key = str(min_id) + '_' + str(max_id)
        # 判断当前会话是否存在
        if key in self.chats:
            self.chats[key].append(self)
        else:
            # 不存在则创建对话，并将当前用户添加进去
            self.chats[key] = [self]

    def on_message(self, message):
        my_id = self.session.get('user').id
        his_id = self.get_cookie('his_id')
        min_id = my_id
        max_id = his_id
        if int(min_id) > int(max_id):
            min_id, max_id = max_id, min_id
        key = str(min_id) + '_' + str(max_id)
        # 聊天记录
        record = ChatRecord(who_send=int(my_id), who_recv=int(his_id), message=message)
        session.add(record)
        session.commit()
        for user in self.chats[key]:
            if user != self:
                user.write_message(message)

    def on_close(self):
        my_id = self.session.get('user').id
        his_id = self.get_cookie('his_id')
        min_id = my_id
        max_id = his_id
        if int(min_id) > int(max_id):
            min_id, max_id = max_id, min_id
        key = str(min_id) + '_' + str(max_id)
        self.chats[key].remove(self)

    def check_origin(self, origin):
        return True


# 退出登录
class LogoutHandler(BaseHandler, SessionMixin):
    def post(self):
        try:
            self.session.delete('user')
            self.write({
                'status': True,
                'data': 'ok'
            })
        except Exception as e:
            print(e)
            self.write({
                'status': False,
                'data': 'fail'
            })


class AdminIndexHandler(BaseHandler):
    def get(self):
        self.render('template/admin/index.html')


class ShopManageHandler(BaseHandler):
    def get(self):
        goods = session.query(Goods).all()
        count = len(goods)
        for good in goods:
            good.classify = session.query(Classify).filter_by(id=int(good.classify)).first().name
        self.render('template/admin/newsType.html', goods=goods, count=count)


class AdminAddGoods(BaseHandler, SessionMixin):
    @tornado.web.authenticated
    def get(self):
        classifies = session.query(Classify).all()
        self.render('template/admin/addgood.html', classifies=classifies)

    @tornado.web.authenticated
    def post(self, *args, **kwargs):
        try:
            name = self.get_argument('name', None)
            price = self.get_argument('price', None)
            desc = self.get_argument('desc', None)
            serves = self.get_argument('serves', None)
            classify = self.get_argument('classify', None)
            status = self.get_argument('status', None)
            good = Goods(name=name, price=float(price), desc=desc, serves=serves, classify=int(classify),
                         status=bool(status), seller=self.session.get('user').id)
            session.add(good)
            session.commit()
            return self.write({'status': True, 'data': 'ok'})
        except Exception as e:
            return self.write({'status': False, 'data': 'fail'})


class GoodImageHandler(BaseHandler, SessionMixin):
    @tornado.web.authenticated
    def post(self, *args, **kwargs):
        try:
            # 获取当前登录用户id
            user_id = self.session.get('user').id
            # 获取当前操作good
            good = session.query(Goods).filter_by(seller=int(user_id)).order_by(Goods.create_time.desc()).first()
            good_id = good.id
            files = self.request.files.get('file')
            if files:
                file = files[0]
                file_suffix = file.get('filename').split('.')[-1]
                # 以用户id新建个人临时目录，判断该目录是否存在决定创建与否
                dirname = '{0}_{1}'.format(user_id, good_id)
                if not os.path.exists(
                        '{0}/static/uploadfiles/shopimages/{1}'.format(os.path.join(os.path.dirname(__file__)),
                                                                       dirname)):
                    os.mkdir(
                        '{0}/static/uploadfiles/shopimages/{1}'.format(os.path.join(os.path.dirname(__file__)),
                                                                       dirname))

                # 添加图片目录
                if good.images == '':
                    good.images = 'uploadfiles/shopimages/{0}'.format(dirname)
                    session.commit()
                with open(
                        '{0}/static/uploadfiles/shopimages/{1}/{2}.{3}'.format(os.path.join(os.path.dirname(__file__)),
                                                                               dirname, time.time(), file_suffix),
                        'wb') as img:
                    img.write(file.get('body'))
                pass
        except Exception as e:
            raise e


def main():
    server = tornado.httpserver.HTTPServer(application)
    port = 8888
    address = '127.0.0.1'
    server.listen(port, address)
    print('http://{0}:{1}'.format(address, port))
    tornado.ioloop.IOLoop.current().start()


if __name__ == '__main__':
    main()
